ECSでCodeDeployを使用したBlue/Green Deploymentがサポートされたので早速試してみた #reinvent
こんにちは、かたいなかです。
先日のre:InventにてECSに対してCodeDeployを使用してBlue/Green Deploymentを行う機能が発表されました。
AWS CodeDeploy/AWS CodePipelineでAWS Fargate/Amazon ECSのCI/CDがサポートされました! #reinvent
個人的にワクワクが止まらくなってしまい、ラスベガスに行ってもないのに早速試してみましたので、内容を紹介します。
今回の記事では、デプロイ後に本番トラフィックを向ける前に本番環境内で動作を確認し、動作確認後リリースを行う、という流れを実装していきます。
Blue/Green Deploymentとは
Blue/Green Deploymentはデプロイの一つのパターンです。
本番環境内に2つの環境を用意し、トラフィックを片方だけに向けておきます。新しいバージョンのデプロイは本番のトラフィックが流れていない方の環境に行い、その環境上で正しく動作していることを確認したら、トラフィックをその環境に切り替えることで新しいバージョンをリリースします。
今回のECSに対してのCodeDeployでのBlue/Green Deploymentでは2つのターゲットグループを作成し、ALB/NLBからのトラフィックを流すターゲットグループを切り替えることでBlue/Green Deploymentを実現しています。
いままでは、CodeDeployの機能としてEC2/On-PremisesおよびAWS Lambdaに対してのBlue/Green Deploymentが提供されていましたが、それがECSでも行えるようになったというわけです。
事前に用意しておく環境
- ECSのクラスタおよびタスク定義を作成しておきます。
- 80番と8080番のポートで受け付けられるALBおよび関連したセキュリティグループ
IAMロール
まず、CodeDeploy用のIAMロールを作成します。
作成するロールには、AWSCodeDeployRoleForECSLimited
というAWSマネージドポリシーをアタッチし、
CodeDeployがECSへのデプロイに関する操作を行えるようにします。
また、信頼ポリシーはCodeDeployがAssumeRoleできるようにするため、以下のようにします。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": [ "codedeploy.amazonaws.com" ] }, "Action": "sts:AssumeRole" } ] }
タスクがタスク実行ロールもしくはタスクロールを使用している場合は以下のようなポリシーもアタッチします。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "iam:PassRole", "Resource": [ "<タスクロールorタスク実行ロールのARN>" ] } ] }
ECSのServiceを作成する
ECSのServiceを作成していきます。
CodeDeployに関する設定以外は、通常のECSのServiceを作成するときと同様ですので説明を省略します。
まず、Serviceを作成していくウィザードの中に、Deployments
という項目が増えています。
ここでは、Deployment type
でBlue/green Deployment(powered by AWS CodeDeploy)
という項目を選択します。
また、Service role for CodeDeploy
には、先に作っておいたCodeDeploy用ロールを選択します。
次に新たな設定が必要になるのはロードバランサとコンテナの関連付けの設定の部分です。
Deployment type
でBlue/Green Deployment
を選択すると、テスト用のリスナーポートに関する設定項目が増えていますのでそちらから、本番トラフィックを8080番ポートでテストできるようにします。
さらに、Blue/Green Deploymentで使用する2つのターゲットグループに関する設定をしていきます。
画像では見えないですがそれぞれのターゲットグループ名のサフィックスを-1
と-2
のように変えています。
あとは通常のECSのServiceの作成と同様に作成していきます。
今回Serviceを作成した際には、コンソール上ではCodeDeploy側でのアプリケーションおよびデプロイグループが作成される際にエラーが出てしまったため、CodeDeployで改めてアプリケーションおよびデプロイグループを作成し、同様の設定を行うことで回避しました。同様のエラーが発生した場合はCodeDeployの画面にも設定項目があるためそちらから設定してください。
本番トラフィックを向ける前に待つようにする設定
今のままですと、デプロイされた際に、新しくデプロイが行われた側のターゲットグループに、トラフィックが自動で流れ始めてしまいます。今回は本番トラフィックを流す前に動作確認を行いたいため、CodeDeploy側で設定を変更します。
デプロイグループの編集画面内のデプロイ設定の項目から、画像のように設定することで、手動でデプロイの処理を続行させるor指定した時間が来るまで、本番トラフィックが古いリビジョンがデプロイされたターゲットグループに向いたままになります。デプロイの処理を続行させる前に指定した時間が来てしまった場合はデプロイが失敗し、停止します。
この状態で、ALBのテスト用のリスナーポート(今回の場合は8080番)にアクセスすると新しくデプロイが行われた側のターゲットグループにアクセスできるため、本番とほとんど同じ状態で動作確認が行えます。
デプロイを行ってみる
ここまでで設定が完了したので実際にデプロイしてみます。
サービスの更新からタスク定義の新しいリビジョンを適用します。
すると、新旧両方のリビジョンが起動した状態になりました。
デプロイが進行中になったため、ECSのServiceの画面のデプロイというタブを開くと、
現在の状況の表示と共に、ロールバックのボタンが表示された状態になっています。このように、ワンクリックでロールバックもできるようになっているわけですね。
さて、この状態で本番のトラフィックが向いている想定であるALBのエンドポイントの80番ポートにアクセスすると、古いリビジョンのアプリケーションの画面が表示されます。今回はNginxのコンソールを古いリビジョンのアプリケーション想定で使用しています。
同様にALBのエンドポイントの8080番ポートにアクセスすると、新しくデプロイしたリビジョンのアプリケーションの画面が表示されます。今回は、Fizzbuzzの簡単なアプリケーションを新しいリビジョンのアプリケーションの想定で使用しています。
正常に動作していることが確認できたので新しいリビジョンに本番トラフィックを向け、リリースを実施してしまいます。
まず、CodeDeployの当該デプロイの画面を開きます。
トラフィックの再ルーティング
ボタンをクリックすると、本番のトラフィック(今回の例ですと80番ポートからくるトラフィック)が新しくデプロイが行われたTargetGroupに向きます。このボタンをクリックし、処理が完了した状態で80番ポートにアクセスしてみると、
新しいリビジョンのアプリケーションにアクセスできました!
デプロイ、動作確認、リリースという一連の流れが実行できるのが確認できました。
まとめ
本番環境へのデプロイの不安を取り除くためにBlue/Greenデプロイを実施しているという話は今までもよく聞いていました。
いままでは独自のスクリプトでTargetGroupを入れ替えるような処理が必要だったのが、今回の新機能でそういった必要がなくなり、気軽にBlue/Greenデプロイを試せるようになったのは個人的に興奮してしまいました。
今回のようなCodeDeploy単独での動作だけでなく、CodePipelineと組み合わせた動作ももちろんサポートされており、今後検証し、記事化できたらと思っています。